package object3.package1;
//向下转型,父类引用赋值给子类引用
public class Test {

     public static void func(Animal animal){
         animal.eat();
     }
     public static Animal createAnimal(){
         return new Cat();
     }
    public static void main(String[] args) {
        //向上转型,父类引用指向子类实例,没有啥太大的限制
       //向上转型(1)
        //当子类对象被父类引用持有时，相当于沿着继承树向上移动（从子类到父类），因此称为向上转型。*****
//        Animal animal = new Cat(); //父类类型引用指向子类实例,两个eat()的返回值类型要一致
//        animal.eat();

        //向上转型(2),空类型
//        func(new Cat());

        //向上转型(3),返回类型
//        Animal animal = createAnimal();
//        animal.eat();

        //      将父类引用强制转换为子类类型,这个才是向下转型*****
        //注:在代码中,向上转型很常见,向下转型很少
        //向下转型,需要先创建一个父类引用,这个父类引用指向子类实例
//        Animal animal = new Cat();
        //向下转型依赖于向上转型,相当于把向上转型的引用,转回来
        //向下转型的要求较多,必须要求父类引用实际上指向的是子类实例,并且需要显式加上类型转换
//        Cat cat = (Cat)animal;
//        animal.eat();
//        animal.meow();//报错,虽然animal指向的是子类的实例,但是类型却是父类的,编译过程中无法找到meow这个方法
        //因为在编译器编译的时候,看到的就是animal就是父类类型的引用,但并未在父类中找到meow,于是报错
        //只有在JVM运行时,才知道animal是指向Cat类型的引用
        //可以想象为一个多分支的条件语句,每个指向不同的引用,根据输入来判断,编译时当然无法判断指向哪个,只有运行时才知道

//判断语句的测试
        Animal animal = new Animal();
        animal.eat();//这样把指向父类的引用再次指向父类,就会直接报错(ClassCastException,类转换异常),可以加一个条件判断语句
        //用来判断该引用是否原来指向子类
        if(animal instanceof Cat){
            Cat cat = (Cat)animal;
        } else{
            System.out.println("类型不匹配");
        }



    }
}
